package com.kingmed.kmss.admin.modules.ums.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.kingmed.kmss.admin.modules.sys.model.SysDataDict;
import com.kingmed.kmss.admin.modules.sys.service.SysDataDictService;
import com.kingmed.kmss.admin.modules.ums.mapper.UmsHrOrgMapper;
import com.kingmed.kmss.admin.modules.ums.model.UmsHrOrg;
import com.kingmed.kmss.admin.modules.ums.model.UmsKmcsOrg;
import com.kingmed.kmss.admin.modules.ums.model.UmsOrganization;
import com.kingmed.kmss.admin.modules.ums.service.UmsHrOrgService;
import com.kingmed.kmss.admin.modules.ums.service.UmsKmcsOrgService;
import com.kingmed.kmss.admin.modules.ums.service.UmsOrganizationService;
import com.kingmed.kmss.common.constant.common.CommonConstants;
import com.kingmed.kmss.common.dto.admin.ums.HRQueryDTO;
import com.kingmed.kmss.common.dto.admin.ums.HrOrgTreeDTO;
import com.kingmed.kmss.common.enums.admin.OrgLevel;
import com.kingmed.kmss.common.enums.admin.OrgType;
import com.kingmed.kmss.common.exception.BusinessException;
import com.kingmed.kmss.common.utils.BeanCopyUtils;
import com.kingmed.kmss.common.utils.MessageUtils;
import com.kingmed.kmss.framework.feign.client.hr.RemoteHRSService;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * EHR组织架构表(数据中台接口) 服务实现类
 * </p>
 *
 * @author WYL
 * @since 2022-12-29
 */
@Slf4j
@Service
public class UmsHrOrgServiceImpl extends ServiceImpl<UmsHrOrgMapper, UmsHrOrg> implements UmsHrOrgService {

    // 组织层级数据字典Code
    private static final String DICT_ORG_LEVEL_CODE = "ums_org_level_code";

    private static final String DICT_ORG_TYPE_CODE = "ums_org_type";

    private static final String HR_ROOT_ID = "00000000-0000-0000-0000-000000000000CCE7AED4";
    private static final Integer HR_QUERY_PAGE_SIZE = 10000;

    @Autowired
    private SysDataDictService dataDictService;
    @Autowired
    private UmsOrganizationService organizationService;
    @Autowired
    private UmsKmcsOrgService umsKmcsOrgService;

    @Autowired
    private RemoteHRSService remoteHRSService;

    @Override
    public int saveBatchData(List<UmsHrOrg> data) {
        this.saveOrUpdateBatch(data);
        return data.size();
    }

    /**
     * 同步HR组织机构数据
     */
    @Transactional
    @Override
    public int refreshHROrgList() {
        // HR系统数据
        List<HrOrgTreeDTO> hrOrgTreeDTOS = this.getHROrgList();
        // 组织级数字典
        Map<String, String> orgLevelMap = this.orgLevelMap();
        // 组织数据类别字典
        Map<String, String> orgTypeMap = this.orgTypeMap();
        // 已同步入库的组织
        Map<String, Long> oldOrgMap = this.getOldOrgMap();

        // 备份HR来源最新数据(ums_hr_org)
        this.getBaseMapper().clearHrOrg();
        this.saveBatch(BeanCopyUtils.copyList(hrOrgTreeDTOS, UmsHrOrg.class));

        // 更新系统数据
        this.updateCrmOrgData(hrOrgTreeDTOS, orgLevelMap, orgTypeMap, oldOrgMap);
        return hrOrgTreeDTOS.size();
    }

    /**
     * 获取已同步的组织数据
     */
    private Map<String, Long> getOldOrgMap() {
        List<UmsOrganization> organizations = organizationService.list();
        if (CollectionUtils.isEmpty(organizations)) {
            return new HashMap<>();
        }
        return organizations.stream().collect(Collectors.toMap(UmsOrganization::getOrgCode, UmsOrganization::getId));
    }

    /**
     * 获取HR系统组织机构信息列表
     */
    private List<HrOrgTreeDTO> getHROrgList() {
        List<HrOrgTreeDTO> hrOrgTreeDTOS = Lists.newArrayList();
        Integer totalSize = 0;
        Integer pageNum = 1;
        Integer endPageNum;
        // 分页查询组织
        do {
            try {
                HRQueryDTO queryDTO = new HRQueryDTO();
                queryDTO.setPageNum(pageNum);
                queryDTO.setPageSize(HR_QUERY_PAGE_SIZE);
                Response response = remoteHRSService.getOrgList(queryDTO);
                log.info("getHROrgList_response：{}", response);
                if (response != null && response.status() == HttpStatus.HTTP_OK) {
                    JSONObject jsonObject = JSONUtil.parseObj(IOUtils.toString(response.body().asInputStream(), StandardCharsets.UTF_8.toString()));
                    JSONObject data = jsonObject.getJSONObject("data");

                    if (data != null) {
                        totalSize = data.getInt("totalSize");
                        JSONArray records = data.getJSONArray("records");
                        if (records != null) {
                            records.forEach(item -> {
                                HrOrgTreeDTO orgTreeDTO = JSONUtil.toBean(JSONUtil.toJsonStr(item), HrOrgTreeDTO.class);
                                hrOrgTreeDTOS.add(orgTreeDTO);
                            });
                        }
                    }
                }
                endPageNum = HR_QUERY_PAGE_SIZE * pageNum;
                pageNum++;
            } catch (Exception e) {
                log.error("获取HR系统组织机构信息列表异常：" + e.getMessage());
                throw new BusinessException(MessageUtils.message("customer_admin_getHROrgList_error"));
            }
        } while (totalSize > endPageNum);
        return hrOrgTreeDTOS;
    }

    public Map<String, String> orgLevelMap() {
        List<SysDataDict> dataDictList = dataDictService.queryByCode(DICT_ORG_LEVEL_CODE);
        return dataDictList.stream().collect(Collectors.toMap(SysDataDict::getDictValue, SysDataDict::getDictKey));
    }

    public Map<String, String> orgTypeMap() {
        List<SysDataDict> dataDictList = dataDictService.queryByCode(DICT_ORG_TYPE_CODE);
        return dataDictList.stream().collect(Collectors.toMap(SysDataDict::getDictValue, SysDataDict::getDictKey));
    }

    /**
     * @param hrOrgTreeDTOS HR数据
     * @param orgLevelMap   orgLevel数据字典
     * @param orgTypeMap    orgType数据字典
     * @param oldOrgMap     上一版本同步的数据
     */
    private void updateCrmOrgData(List<HrOrgTreeDTO> hrOrgTreeDTOS,
                                  Map<String, String> orgLevelMap, Map<String, String> orgTypeMap, Map<String, Long> oldOrgMap) {
        // 已存在的ums_kmcs_org中的组织
        List<UmsKmcsOrg> umsKmcsOrgList = this.getUmsKmcsOrgList();
        List<UmsOrganization> result = Lists.newArrayList();
        // 保存数据：新增Org数据先生成主键ID
        for (HrOrgTreeDTO hrOrg : hrOrgTreeDTOS) {
            UmsOrganization umsOrganization = this.toCrmOrg(hrOrg, orgLevelMap, orgTypeMap, oldOrgMap);
            //以ums_kmcs_org为基准，不让oa同步数据再次刷新ums_organization数据
            result.add(this.handlerOrgLevel(umsOrganization,umsKmcsOrgList));
        }
        organizationService.saveOrUpdateBatch(result);
        // 更新parentID
        List<UmsOrganization> newOrgList = organizationService.list();
        oldOrgMap = newOrgList.stream().collect(Collectors.toMap(UmsOrganization::getOrgCode, UmsOrganization::getId));
        for (UmsOrganization umsOrg : newOrgList) {
            umsOrg.setParentId(oldOrgMap.get(umsOrg.getOrgParentCode()));
            // 直属公司
            umsOrg.setCompanyId(oldOrgMap.get(umsOrg.getCompanyHrId()));
        }
        organizationService.saveOrUpdateBatch(newOrgList);
        // 缓存组织数据
        organizationService.redisAllOrg();
    }

    /**
     * HR系统数据对象转crm数据对象
     */
    private UmsOrganization toCrmOrg(HrOrgTreeDTO hrOrg, Map<String, String> orgLevelMap, Map<String, String> orgTypeMap, Map<String, Long> oldOrgMap) {
        UmsOrganization org = new UmsOrganization();
        if (HR_ROOT_ID.equals(hrOrg.getFid())) {
            // CRM系统根组织固定id
            org.setId(1L);
            org.setParentId(0L);
        } else {
            org.setId(oldOrgMap.get(hrOrg.getFid()));
            org.setParentId(oldOrgMap.get(hrOrg.getFparentid()));
        }
        org.setOrgCode(hrOrg.getFid());
        org.setOrgParentCode(hrOrg.getFparentid());
        org.setOrgName(hrOrg.getFnameL2());
        // 组织类型
        org.setOrgType(OrgType.getCodeByHrID(hrOrg.getFadminaffiliationtype()));
        // 组织层级
        if (StrUtil.contains(hrOrg.getFnameL2(), "大区") && HR_ROOT_ID.equals(hrOrg.getFparentid())) {
            org.setLevel(OrgLevel.REGION.getCode());
        } else {
            org.setLevel(orgLevelMap.get(hrOrg.getFlayertype()) == null ? 0 : Integer.parseInt(orgLevelMap.get(hrOrg.getFlayertype())));
        }
        // 是否归档（0=可用，1=失效）
        org.setStatus(StrUtil.isEmpty(hrOrg.getFissealup()) ? UmsOrganizationServiceImpl.STATUS_YES : Integer.parseInt(hrOrg.getFissealup()));
        // 直属公司
        org.setCompanyHrId(hrOrg.getFcompanyid());
        org.setDeleteFlag(CommonConstants.FLG_NO);
        // 不能直接用当前时间，ums_organization的创建和更新时间，用UmsHrOrg的fcreatetime和flastupdatetime
        org.setCreateTime(hrOrg.getFcreatetime());
        org.setUpdateTime(hrOrg.getFlastupdatetime());//设置更新时间(会被框架覆盖)
        return org;
    }

    /**
     * 根据ums_kmcs_org表中数据处理org_level
     * 关键逻辑：ums_kmcs_org如果预设的org_level和OrgParentCode，那么同步oa时，umsOrganization不能改，以ums_kmcs_org为准，解决孙公司提级到子公司的问题
     */
    private UmsOrganization handlerOrgLevel(UmsOrganization umsOrganization, List<UmsKmcsOrg> umsKmcsOrgList) {
        if(CollUtil.isNotEmpty(umsKmcsOrgList)) {
            for(UmsKmcsOrg umsKmcsOrg : umsKmcsOrgList){
                if(StrUtil.isNotEmpty(umsOrganization.getOrgCode())
                        && umsOrganization.getOrgCode().equals(umsKmcsOrg.getOrgCode())){
                    umsOrganization.setLevel(umsKmcsOrg.getOrgLevel());
                    umsOrganization.setOrgParentCode(umsKmcsOrg.getOrgParentCode());
                    break;
                }
            }
        }

        return umsOrganization;
    }

    /**
     * 获取ums_kmcs_org组织数据
     */
    private List<UmsKmcsOrg> getUmsKmcsOrgList() {
        return umsKmcsOrgService.getUmKmcsOrgList();
    }

    /*@Override
    public void getOrgList(HRQueryDTO queryDTO) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", authorization);
        headers.put("Content-Type", "application/json");
        String response = HttpTookit.doPost(serviceUrl+"/dcai/api/v1/shrOaOrg/findByPage", JSONUtil.toJsonStr(queryDTO), headers);
        log.info("getOrgList:{}", response);
    }*/

}
